package com.demo.api.service.logs;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.demo.api.cache.UrlCache;
import com.demo.api.controller.BaseController;
import com.demo.api.interceptor.user.AuthUserInfo;
import com.demo.client.model.user.SysInterface;
import com.demo.client.model.user.SysUser;
import com.demo.api.vo.logs.LogReq;
import com.demo.api.vo.logs.LogRes;
import com.demo.client.mapper.log.SysLogMapper;
import com.demo.client.model.log.SysLog;
import com.demo.core.enums.ErrorEnum;
import com.demo.core.enums.OftenEnum;
import com.demo.core.redis.RedisTableCache;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class SysLogServiceImpl extends BaseController implements ISysLogService {

    @Resource
    private SysLogMapper logMapper;

    @Resource
    private RedisTableCache redisTableCache;

    @Resource
    private UrlCache urlCache;


    @Override
    public IPage<LogRes.Pages> getLogPage(Page<SysLog> page, LogReq req) {
        LambdaQueryWrapper<SysLog> wrapper = Wrappers.lambdaQuery(SysLog.class)
                .eq(req.getCode() != null, SysLog::getCode, req.getCode())
                .eq(StringUtils.isNotBlank(req.getIp()), SysLog::getIp, req.getIp())
                .eq(req.getUserId() != null, SysLog::getUserId, req.getUserId())
                .eq(req.getType() != null, SysLog::getType, req.getType())
                .eq(StringUtils.isNotBlank(req.getMethodType()), SysLog::getMethodType, req.getMethodType())
                .like(StringUtils.isNotBlank(req.getTitle()), SysLog::getTitle, req.getTitle())
                .like(StringUtils.isNotBlank(req.getModuleName()), SysLog::getModuleName, req.getModuleName())
                .like(StringUtils.isNotBlank(req.getUrl()), SysLog::getUrl, req.getUrl()).orderByDesc(SysLog::getId);
        return logMapper.selectPage(page, wrapper).convert(e -> {
            LogRes.Pages pages = BeanUtil.copyProperties(e, LogRes.Pages.class);
            if (pages.getUserId() != null) {
                SysUser user = redisTableCache.get(SysUser.class, pages.getUserId());
                assert user != null;
                pages.setUserName(user.getUserName());
            }
            return pages;
        });
    }


    @Override
    public void createErrorLog(HttpServletRequest request, ErrorEnum errorEnum, String msg) {
        String url = request.getRequestURI();
        SysInterface sysInterface = urlCache.getInterface(url);
        if (sysInterface == null) {
            log.error("该接口不存在缓存中：{}", url);
            return;
        }
        Map<String, String[]> map = request.getParameterMap();
//        long time = Long.parseLong(request.getAttribute("times").toString());
        SysLog sysLog = SysLog.builder()
                .ip(getIpAddr(request))
                .methodType(request.getMethod())
                .moduleName(sysInterface.getClassRemark())
//                .times(System.currentTimeMillis() - time)
                .title(sysInterface.getRemarks())
                .type(getType(sysInterface.getToken()))
                .url(request.getRequestURI())
                .userId(getUserId(sysInterface.getToken()))
                .code(errorEnum.getCode())
                .errorMsg(StringUtils.isNotBlank(msg) ? msg : errorEnum.getMsg())
                .requestParam(getParam(map))
                .build();
        try {
            logMapper.insert(sysLog);
        } catch (Throwable e) {
            log.error("插入日志失败：{}", e);
        }
    }

    @Override
    public List<?> getParam(Map<String, String[]> map) {
        Map<String, Object> res = new HashMap<>();
        List<Map<String, Object>> list = new ArrayList<>();
        for (Map.Entry<String, String[]> entry : map.entrySet()) {
            res.put(entry.getKey(), entry.getValue()[0]);
        }
        list.add(res);
        return list;
    }

    @Override
    public Integer getType(boolean b) {
        if (b) {
            return OftenEnum.InterfaceType.POWER.code();
        }
        return OftenEnum.InterfaceType.PUBLIC.code();
    }

    @Override
    public Long getUserId(boolean b) {
        if (b) {
            return AuthUserInfo.getUserId();
        }
        return null;
    }

}
